#include "bsp.h"
#include "mrfi.h"
#include "nwk_types.h"
#include "nwk_api.h"
#include "nwk.h"
#include "bsp_leds.h"
#include "bsp_buttons.h"
#include "CTC.h"
#include "stdlib.h"

static uint8_t RxCallBack(linkID_t);

uint8_t numRCRs = 0;
uint8_t numRTSs = 0;

uint8_t RCRsleepTime = DEFAULT_RCR_SLEEP_TIME;
uint8_t RTSsleepTime = DEFAULT_RTS_SLEEP_TIME;

static linkID_t linkID = 0;
uint8_t receiveBuffer[3] = {0,0,0};
uint8_t length;
volatile uint8_t receivedBroadcast = 0;
volatile uint8_t receivedRequest = 0;
volatile linkID_t receivedLinkID = 0;
uint8_t open = 1;

void main(void)
{
	RCR_t** RCRs;
	RTS_t** RTSs;
	
	RCR_t* RCR;
	RTS_t* RTS;
	
	WDTCTL = WDTPW | WDTHOLD;												// Turn off watchdog timer
	BSP_Init();
	SMPL_Init(RxCallBack);													// Start SimpliciTI with the callback function RxCallBack
	
	SMPL_Ioctl(IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_RXON, 0);		// Enable radio receive
	
	RCRs = (RCR_t**)malloc(sizeof(RCR_t*));
	RTSs = (RTS_t**)malloc(sizeof(RTS_t*));
 
	while(1)
	{
		//BSP_TOGGLE_LED2();
		if(receivedBroadcast)
		{
			// LinkListen will block for ~5 seconds. This should be enough time to wait.
			// We want to only try to link once just in case we get an errant broadcast
			// request from something already linked.
			SMPL_LinkListen(&linkID);
			receivedBroadcast = 0;
		}
		if(receivedRequest)
		{		 	
		 	if(SMPL_Receive(receivedLinkID, receiveBuffer, &length) != SMPL_SUCCESS)
		 	{
		 		// TODO: handle problem
		 		continue;
		 	}
		 	if(length != 3)
		 	{
		 		// TODO: handle problem
		 		continue;
		 	}
		 	
		 	switch(receiveBuffer[0])
		 	{
		 		// identification frame from an RCR
		 		case RCR_IDENT:
			 		RCR = createNewRCR(receivedLinkID, receiveBuffer[1], RCRsleepTime, receiveBuffer[2]);
				 	RCRs = addNewRCR(RCRs, numRCRs, RCR);
				 	numRCRs++;
		 			break;
		 		// identification frame from an RTS
		 		case RTS_IDENT:
		 			RTS = createNewRTS(receivedLinkID, receiveBuffer[1], RTSsleepTime, receiveBuffer[2]);
				 	RTSs = addNewRTS(RTSs, numRTSs, RTS);
				 	numRTSs++;
		 			break;
		 		// command request from an RCR
		 		case RCR_REQ:
			 		if(isRCR(RCRs, numRCRs, receivedLinkID))
				 	{
					 	updateRCR(RCRs, numRCRs, receivedLinkID, receiveBuffer[2]);
					 	ackRCR(RCRs, numRCRs, receivedLinkID);
				 	}
			 		break;
			 	// command request from RTS
		 		case RTS_REQ:
			 		if(isRTS(RTSs, numRTSs, receivedLinkID))
				 	{
				 		//BSP_TOGGLE_LED2();
					 	updateRTS(RTSs, numRTSs, receivedLinkID, receiveBuffer[1], receiveBuffer[2]);
					 	ackRTS(RTSs, numRTSs, receivedLinkID);
					 	
					 	BSP_TOGGLE_LED2();
					 	
					 	/*
					 	 * RTS Data test Code
					 	 * 
					 	RTSIndex = findRTSbyLinkID(RTSs, numRTSs, receivedLinkID);
					 	
					 	if((RTSs[RTSIndex]->temp  == 27) && (RTSs[RTSIndex]->battLife == 50))
					 		BSP_TURN_ON_LED1();
					 	else
					 		BSP_TURN_ON_LED2();
					 	*/
				 	}
			 		break;
		 		default:
		 			break;
		 	}
			receivedRequest = 0;
		}
	}
}

static uint8_t RxCallBack(linkID_t lid)
{
	//BSP_TOGGLE_LED2();
	// Is this a broadcast packet? If so, assume someone is 
	// trying to connect. We don't need to keep the frame.
	if(lid == SMPL_LINKID_USER_UUD)
	{
		receivedBroadcast = 1;
		return DISCARD_FRAME;
	}
	// If it's not a broadcast packet this is from an RCR or RTS.
	// Save the link ID and the frame.
	receivedRequest = 1;
	receivedLinkID = lid;
	return KEEP_FRAME;
}
